/**
  * @file main.cpp
  * @brief Fichier contenant la fonction \p main, point d'entrée du programme.
  * @author Thibault Merle et Guillaume Poussel
  */
#include <limits>
#include <string>
#include <sys/time.h>

#include <QtGui/QApplication>
#include "ui/MainWindow.h"

#include "algo/RandomAlgorithm.h"
#include "algo/DacAlgorithm.h"


using namespace std;

int main(int argc, char** argv) {
    srand(time(NULL));
    // Si il n'y a pas d'arguments, lancement de l'interface graphique
    if (argc <= 1) {
        QApplication a(argc, argv);
        MainWindow w;
        w.show();

        return a.exec();
    } else if (argc != 4) {
        cerr << "Erreur dans les arguments" << endl;
        cerr << "Utilisation: " << argv[0] << " <nb_points> <algo> <optimisation>" << endl;
        cerr << "\tnb_points : Nombre de points" << endl;
        cerr << "\talgo : Choix de l'algorithme : DIVISER ou RANDOM" << endl;
        cerr << "\toptimisation : 1 pour utiliser l'optimisation du losange, 0 sinon." << endl;
        return -1;
    } else {
        unsigned long int nb_points = strtod(argv[1], NULL);
        if (nb_points <= 0) {
            cerr << "Erreur avec le nombre de points" << endl;
            return -1;
        }
        bool with_optimization = atoi(argv[3]);
        string input_algo = argv[2];

        Algorithm* algo;
        if (input_algo == "DIVISER") {
            algo = new DaCAlgorithm();
        } else if (input_algo == "RANDOM") {
            algo = new RandomAlgorithm();
        } else {
            cerr << "Algorithme non reconnu (DIVISER ou RANDOM)" << endl;
            return -1;
        }

        if (with_optimization) {
            algo->with_diamond_opti(with_optimization);
        }
        point_list points = point_list::get_random_points(nb_points,
                                                          -50000, 50000);

        // Calcul du temps d'exécution
        struct timeval begin_time, end_time;
        if(0 != gettimeofday(&begin_time, NULL)) {
            cerr << "Erreur initialisation temps de debut";
            return -1;
        }
        algo->compute_hull(points); // Appel de l'algorithme
        if(0 != gettimeofday(&end_time, NULL)) {
            cerr <<  "Erreur initialisation temps de fin";
            return -1;
        }
        double duree = (end_time.tv_sec + end_time.tv_usec*1E-6) - (begin_time.tv_sec + begin_time.tv_usec*1E-6);
        cout << duree; // Affichage du temps en secondes

        // Libération de la mémoire
        delete algo;
        while (!points.empty()) {
            delete points.back();
            points.pop_back();
        }
    }
}
